package com.societyGames.flashForms
{
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;

public class DockContainer extends Sprite
{
  private var _desiredWidth:Number;
  private var _desiredHeight:Number;
  private var _items:Vector.<DockItem> = new Vector.<DockItem>();

  public function DockContainer()
  {
  }

  public override function set width(value:Number):void
  {
    if (value != this._desiredWidth)
    {
      this._desiredWidth = value;
      calculate();
    }
  }

  public override function set height(value:Number):void
  {
    if (value != this._desiredHeight)
    {
      this._desiredHeight = value;
      calculate();
    }
  }

  public function addItem(item:DisplayObject, dockType:DockType, dockUnitType:DockUnitType, units:Number):void
  {
    if (units < 0)
    {
      throw new ArgumentError("Parameter \"units\" cannot be less than 0.");
    }
    if (dockUnitType == DockUnitType.percent && units > 1)
    {
      throw new ArgumentError("Parameter \"units\" cannot be greater than 1.0 if it is a percent.");
    }
    if (dockUnitType == DockUnitType.item)
    {
      var changeSize:IChangeSize = item as IChangeSize;
      if (changeSize != null)
      {
        changeSize.sizeChangedEventObject.addEventListener(itemSizeChangedHandler);
      }
    }
    this._items.push(new DockItem(item, dockType, dockUnitType, units));
    calculate();
  }

  private function itemSizeChangedHandler(event:Event):void
  {
    calculate();
  }

  public function calculate():void
  {
    var left:Number = 0;
    var right:Number = this._desiredWidth;
    var top:Number = 0;
    var bottom:Number = this._desiredHeight;
    //Go through the dock items
    for (var itemIndex:int = 0; itemIndex < _items.length; itemIndex++)
    {
      var item:DockItem = this._items[itemIndex];
      var widthLeft:Number = right - left;
      var heightLeft:Number = bottom - top;
      //If we have any room left to actually render.
      if (widthLeft > 0 && heightLeft > 0)
      {
        var widthPixels:Number;
        var heightPixels:Number;
        switch (item.dockUnitType)
        {
          case DockUnitType.pixel:
            widthPixels = item.units;
            heightPixels = item.units;
            break;
          case DockUnitType.percent:
            widthPixels = item.units * widthLeft;
            heightPixels = item.units * heightLeft;
            break;
          case DockUnitType.item:
            widthPixels = item.item.width;
            heightPixels = item.item.height;
            break;
        }

        switch (item.dockType)
        {
          case DockType.left:
            //Take all the vertical space
            item.item.height = heightLeft;
            //Width might have changed because of setting the height.
            if (item.dockUnitType == DockUnitType.item)
            {
              widthPixels = item.item.width;
            }
            //Give as much width as possible
            if (widthPixels > widthLeft)
            {
              widthPixels = widthLeft;
            }
            //Take as much width requested as possible.
            item.item.width = widthPixels;
            //Put it in the right place
            item.item.x = left;
            item.item.y = top;
            //Deduct from available.
            left += widthPixels;
            break;
          case DockType.right:
            //Take all the vertical space
            item.item.height = heightLeft;
            //Width might have changed because of setting the height.
            if (item.dockUnitType == DockUnitType.item)
            {
              widthPixels = item.item.width;
            }
            //Give as much width as possible
            if (widthPixels > widthLeft)
            {
              widthPixels = widthLeft;
            }
            //Take as much width as requested and available.
            item.item.width = widthPixels;
            //Put it in the right place
            item.item.x = right - widthPixels;
            item.item.y = top;
            //Deduct from available.
            right -= widthPixels;
            break;
          case DockType.top:
            //Take all the horizontal space
            item.item.width = widthLeft;
            //Height might have changed because of setting the height.
            if (item.dockUnitType == DockUnitType.item)
            {
              heightPixels = item.item.height;
            }
            //Give as much height as possible
            if (heightPixels > heightLeft)
            {
              heightPixels = heightLeft;
            }
            //Take as much height as requested and available.
            item.item.height = heightPixels;
            //Put it in the right place
            item.item.x = left;
            item.item.y = top;
            //Deduct from available.
            top += heightPixels;
            break;
          case DockType.bottom:
            //Take all the horizontal space
            item.item.width = widthLeft;
            //Height might have changed because of setting the height.
            if (item.dockUnitType == DockUnitType.item)
            {
              heightPixels = item.item.height;
            }
            //Give as much height as possible
            if (heightPixels > heightLeft)
            {
              heightPixels = heightLeft;
            }
            //Take as much height as requested.
            item.item.height = heightPixels;
            //Put it in the right place
            item.item.x = left;
            item.item.y = bottom - heightPixels;
            //Deduct from available.
            bottom -= heightPixels;
            break;
          case DockType.fill: //Take the rest of the space.
            item.item.x = left;
            item.item.y = top;
            item.item.width = widthLeft;
            item.item.height = heightLeft;
            left += widthLeft;
            top += heightLeft;
            break;
        }
      }
      else //No room left, hide it.
      {
        item.item.width = 0;
        item.item.height = 0;
      }
    }

    if (itemIndex >= _items.length) //if we hit end of array, addItemIndex will be one past where we actually want to be.
    {
      itemIndex--;
    }

    //Add children in reverse order.
    for (; itemIndex >= 0; itemIndex--)
    {
      this.addChild(_items[itemIndex].item);
    }
  }
}
}

import com.societyGames.flashForms.DockType;
import com.societyGames.flashForms.DockUnitType;

import flash.display.DisplayObject;

class DockItem
{
  private var _item:DisplayObject;
  private var _dockType:DockType;
  private var _dockUnitType:DockUnitType;
  private var _units:Number;

  public function DockItem(item:DisplayObject, dockType:DockType, dockUnitType:DockUnitType, units:Number)
  {
    this._item = item;
    this._dockType = dockType;
    this._dockUnitType = dockUnitType;
    this._units = units;
  }

  public function get item():DisplayObject
  {
    return this._item;
  }

  public function get dockType():DockType
  {
    return this._dockType;
  }

  public function get dockUnitType():DockUnitType
  {
    return this._dockUnitType;
  }

  public function get units():Number
  {
    return this._units;
  }
}